fix(routes): take a route's handler from the last argument, not the first - #2009
Conversation
…irst
Express, Fastify, gin and Laravel all put middleware between the route
path and the handler, and the handler comes last:
routerGet("/users", requireAuth, rateLimit, listUsers);
extract_handler_arg returned the FIRST argument that looked like a
function reference, so requireAuth won and the HANDLES edge pointed at
the middleware instead of listUsers. That is a wrong edge, not a
missing one, and it misleads anyone tracing a request through the
graph.
The scan bound hid a second fault. An arrow function matches none of
the accepted node kinds, so three inline middlewares pushed the real
handler past MAX_HANDLER_SCAN and no handler came back at all.
The loop now examines every argument and keeps the last eligible one.
Nothing that follows a handler matches the accepted kinds either, since
an options argument is an object node, so the last match is the
handler. HANDLER_START_IDX stays, because argument 0 really is the
path. MAX_HANDLER_SCAN had no other use and is gone.
A two-argument route has one eligible argument, so first and last agree
and the existing Express, Fastify, gin and Laravel route tests are
unchanged.
Both tests fail without the change, the first reporting "requireAuth"
where "listUsers" belongs and the second reporting no handler at all.
Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
|
Approved, and this is the more consequential of your two route fixes — a wrong edge, not a missing one. Verified on
A wrong edge is worse than a missing one, and worth saying why: a missing Taking the last eligible argument is the right rule for the frameworks named — Express, Fastify, gin and Laravel all place middleware between path and handler with the handler last — and your justification is the part that makes it safe: nothing that legitimately follows a handler matches the accepted kinds, since an options argument is an One thing to keep an eye on, not a blocker. Removing Both faults reproduced red before the change, with the distinct failure text for each ( Merging on green. Our Actions queue is heavily backlogged at the moment, so expect a wait — nothing to do with this PR. #2008 touches |
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
|
Merged as Worth restating why: Removing On verificationYour green was 35/35, but The one thing I noted at review still stands as a watch item, not a blocker: That is your fourth merge today, after #2008, #1986 and #1877. |
Express, Fastify, gin and Laravel all put middleware between the route path and the handler, and the handler comes last:
extract_handler_argreturned the first argument that looked like a function reference, sorequireAuthwon.second_arg_namecarries that value intopass_calls.c, which resolves it into the HANDLES edge target — so the edge pointed at the middleware instead oflistUsers. That is a wrong edge rather than a missing one, and it misleads anyone tracing a request through the graph.The scan bound hid a second fault. An arrow function matches none of the accepted node kinds, so three inline middlewares pushed the real handler past
MAX_HANDLER_SCANand no handler came back at all.Both faults reproduced before any change
Two tests in this PR, red on current
main:The change
The loop examines every argument and keeps the last eligible one. Nothing that follows a handler matches the accepted kinds either — an options argument is an
objectnode — so the last match is the handler.HANDLER_START_IDXstays, because argument 0 really is the route path.MAX_HANDLER_SCANhad no other use and is removed.Why existing route tests do not move
A two-argument route has one eligible argument, so first and last are the same value.
handles_express_ts,handles_fastify_js,handles_gin_go,handles_laravel_phpand bothhandles_laravel_facade_*_issue952tests pass unchanged.Why the tests live in
test_extraction.cThe
test_edge_types_probe.charness offerset_edge_present,et_routes_exactandet_calls_to_name_parallel, and none of them says which node a HANDLES edge points at. A wrong handler still yields one HANDLES edge and the right Route name, so a probe test would have passed while the bug stood.test_extraction.calready readsfirst_string_argdirectly; these tests assertsecond_arg_namebeside it, which is the value being changed.Note for anyone with an existing index
This changes which function a route resolves to, so already-indexed projects carry the old handler edges until they are re-indexed.
Full C suite on this branch: 7782 passed, 7 skipped. Two
test_cli.cinstall/uninstall tests fail on my machine with or without this change, because they read the coding agents actually installed there.